﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;
using Microsoft.SharePoint.Utilities;

namespace ADProfileSync
{
    class TJSync : SPJobDefinition
    {

        public TJSync()
            : base()
        {

        }

        public TJSync(string jobName, SPService service, SPServer server, SPJobLockType targetType)

            : base(jobName, service, server, targetType)
        {

        }

        public TJSync(string jobName, SPWebApplication webApplication)
            : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
        {
            this.Title = jobName;
        }

        public override void Execute(Guid targetInstanceId)
        {
            if (!Properties.ContainsKey("site-id"))
                return;

            var siteId = (Guid)Properties["site-id"];

            using (SPSite site = new SPSite(siteId))
            using (SPWeb web = site.OpenWeb())
            {
                SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;

                // Add Needed Site Columns to Site Info User List (WorkPhone)
                SPList list = web.SiteUserInfoList;

                diagSvc.WriteTrace(0, new SPDiagnosticsCategory("TJSync", TraceSeverity.Monitorable, EventSeverity.Verbose), TraceSeverity.Monitorable, "Verifying if WorkPhone field is Created in Site User Info List ", null);
                // Gets the default list's content type and add WorkPhone Property.
                SPContentType contentType = list.ContentTypes[0];
                if (!contentType.Fields.ContainsField("WorkPhone"))
                {
                    SPField field = web.Fields[SPBuiltInFieldId.WorkPhone];
                    SPFieldLink fieldLink = new SPFieldLink(field);
                    contentType.FieldLinks.Add(fieldLink);
                    contentType.Update(true);
                    diagSvc.WriteTrace(0, new SPDiagnosticsCategory("TJSync", TraceSeverity.Monitorable, EventSeverity.Verbose), TraceSeverity.Monitorable, "Successfully linked WorkPhone Site Colunm to Site User Info List ", null);
                }
                else
                {
                    diagSvc.WriteTrace(0, new SPDiagnosticsCategory("TJSync", TraceSeverity.Monitorable, EventSeverity.Verbose), TraceSeverity.Monitorable, "WorkPhone already exists in Site User Info List ", null);
                }


                // Read All Users from Site Collection
                foreach (SPUser user in web.AllUsers)
                {
                    if (!user.IsDomainGroup)
                    {
                        #region Import Profile Properties
                        diagSvc.WriteTrace(0, new SPDiagnosticsCategory("TJSync", TraceSeverity.Monitorable, EventSeverity.Verbose), TraceSeverity.Monitorable, "Starting syncing profile of user: " + user.LoginName, null);

                        // Locate user using Sid in AD
                        PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
                        UserPrincipal domainUser = UserPrincipal.FindByIdentity(ctx, System.DirectoryServices.AccountManagement.IdentityType.Sid, user.Sid);
                        if (domainUser != null)
                        {
                            DirectoryEntry de = (domainUser.GetUnderlyingObject() as DirectoryEntry);

                            SPListItem itemUser = web.SiteUserInfoList.GetItemById(user.ID);

                            if (!string.IsNullOrEmpty(domainUser.EmailAddress))
                                itemUser[SPBuiltInFieldId.EMail] = domainUser.EmailAddress;

                            using (new SPMonitoredScope("GetTelephoneFromAD"))
                            {
                                try
                                {
                                    object workPhone = de.InvokeGet("telephoneNumber");
                                    if (workPhone != null)
                                        itemUser[SPBuiltInFieldId.WorkPhone] = workPhone;
                                }
                                catch { }
                            }

                            using (new SPMonitoredScope("GetDepartmentFromAD"))
                            {
                                try
                                {
                                    object department = de.InvokeGet("department");
                                    if (department != null)
                                        itemUser[SPBuiltInFieldId.Department] = department;
                                }
                                catch { }
                            }

                            itemUser.Update();

                            diagSvc.WriteTrace(0, new SPDiagnosticsCategory("TJSync", TraceSeverity.Monitorable, EventSeverity.Verbose), TraceSeverity.Monitorable, "Successfully synced profile of user: " + user.LoginName, null);
                        }
                        #endregion
                    }
                }
            }
        }
    }
}
